package personnal.jonat.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableModel;

import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

import personnal.jonat.OutCome;
import personnal.jonat.StudentExtractor;
import personnal.jonat.StudentOutComeGenerator;

public class JonatToolUI extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;

	private static final String QUIT_ACTION_COMMAND = "quit";
	private static final Logger logger = Logger.getLogger(JonatToolUI.class);

	Properties configurationProperties;

	private JTextField inputFileField;
	private JTextField outputDirectoryField;

	private JTextField studentCountField;

	private JTextField skillCountField;

	public JonatToolUI() {
		super("Jonat's TeacherTool :)");
		Properties fileProperties = new Properties();
		try {
			fileProperties
					.load(new FileInputStream("configuration.properties"));
			logger.info("Chargement du fichier configuration.properties");
		} catch (IOException e) {
			logger.info("Fichier configuration.properties introuvable", e);
		}
		this.configurationProperties = fileProperties;
		createComponents();
	}

	protected void createComponents() {
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		Container contentPane = getContentPane();
		BoxLayout layout = new BoxLayout(contentPane, BoxLayout.Y_AXIS);
		contentPane.setLayout(layout);
		contentPane.add(createWarningMessagePanel());
		contentPane.add(Box.createVerticalStrut(10));
		contentPane.add(createBrowseInputFilePanel());
		if (configurationProperties.isEmpty()) {
			contentPane.add(Box.createVerticalStrut(10));
			contentPane.add(createConfigPanel());
		}
		contentPane.add(Box.createVerticalStrut(10));
		contentPane.add(createConfigurationPanel());
		contentPane.add(Box.createVerticalStrut(10));
		contentPane.add(createBrowseOutputDirectoryPanel());
		contentPane.add(Box.createVerticalStrut(10));
		contentPane.add(createBottomButtonPanel());
		contentPane.add(Box.createVerticalStrut(10));
		// setSize(600, 300);
		pack();
		setResizable(true);
		setLocationByPlatform(true);
		setVisible(true);
	}

	private JPanel createWarningMessagePanel() {
		JPanel warningMessagePanel = new JPanel();
		warningMessagePanel.setBorder(createBorder("Attention"));
		warningMessagePanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		JLabel messageLabel = new JLabel(
				"   Pensez à mettre à jour le fichier Excel modèle (template.xls) en fonction du nombre de matière   ");
		messageLabel.setForeground(Color.RED);
		warningMessagePanel.add(messageLabel);
		return warningMessagePanel;
	}

	private JPanel createBottomButtonPanel() {
		JPanel generateButtonPanel = new JPanel();
		generateButtonPanel.setLayout(new FlowLayout(FlowLayout.CENTER));

		JButton generateButton = new JButton("Générer");
		generateButton.addActionListener(this);
		generateButtonPanel.add(generateButton);

		JButton quitButton = new JButton("Quitter");
		quitButton.setActionCommand(QUIT_ACTION_COMMAND);
		quitButton.addActionListener(this);
		generateButtonPanel.add(quitButton);

		return generateButtonPanel;
	}

	private Component createConfigurationPanel() {
		JPanel configPanel = new JPanel();
		configPanel.setBorder(createBorder("Configuration"));
		configPanel.setLayout(new BorderLayout());

		TableModel tableData = new PropertiesTableModel(configurationProperties);
		JTable configTable = new JTable(tableData);
		configPanel.add(configTable.getTableHeader(), BorderLayout.NORTH);
		configPanel.add(configTable, BorderLayout.CENTER);
		return configPanel;
	}

	private JPanel createConfigPanel() {
		JPanel configPanel = new JPanel();
		configPanel.setBorder(createBorder("Configuration"));
		configPanel.setLayout(new BoxLayout(configPanel, BoxLayout.Y_AXIS));

		JPanel panel = new JPanel();
		panel.setLayout(new FlowLayout(FlowLayout.LEFT));
		panel.add(new JLabel("Nombre d'élèves : "));
		this.studentCountField = new JTextField("", 20);
		panel.add(this.studentCountField);
		configPanel.add(panel);

		panel = new JPanel();
		panel.setLayout(new FlowLayout(FlowLayout.LEFT));
		panel.add(new JLabel("Nombre de matières : "));
		this.skillCountField = new JTextField("", 20);
		panel.add(this.skillCountField);
		configPanel.add(panel);

		return configPanel;
	}

	private TitledBorder createBorder(String title) {
		Border border = BorderFactory.createLineBorder(Color.DARK_GRAY);
		return BorderFactory.createTitledBorder(border, title);
	}

	private JPanel createBrowseInputFilePanel() {
		JPanel browsePanel = new JPanel();
		browsePanel.setLayout(new BoxLayout(browsePanel, BoxLayout.Y_AXIS));
		browsePanel.setBorder(createBorder("Fichier de notes"));
		browsePanel.add(new JLabel(
				"Sélectionner le fichier contenant les notes :"));

		JPanel panel = new JPanel();
		this.inputFileField = new JTextField("", 30);
		panel.add(this.inputFileField);
		JButton browseButton = new JButton("Parcourir");
		browseButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser(".");
				fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
				fileChooser.setMultiSelectionEnabled(false);
				fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
				fileChooser.setFileFilter(new FileNameExtensionFilter(
						"Fichier Excel", "xls"));
				int dialogReturn = fileChooser.showOpenDialog(JonatToolUI.this);
				if (dialogReturn == JFileChooser.APPROVE_OPTION) {
					JonatToolUI.this.inputFileField.setText(fileChooser
							.getSelectedFile().getAbsolutePath());
				}
			}
		});
		panel.add(browseButton);
		browsePanel.add(panel);
		return browsePanel;
	}

	private JPanel createBrowseOutputDirectoryPanel() {
		JPanel browseOutputPanel = new JPanel();
		browseOutputPanel.setLayout(new BoxLayout(browseOutputPanel,
				BoxLayout.Y_AXIS));
		browseOutputPanel.setBorder(createBorder("Répertoire de sortie"));
		browseOutputPanel.add(new JLabel(
				"Sélectionner le répertoire de génération des fichiers :"));

		JPanel panel = new JPanel();
		this.outputDirectoryField = new JTextField("", 30);
		panel.add(this.outputDirectoryField);
		JButton browseButton = new JButton("Parcourir");
		browseButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser(".");
				fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
				fileChooser.setMultiSelectionEnabled(false);
				fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				int dialogReturn = fileChooser.showOpenDialog(JonatToolUI.this);
				if (dialogReturn == JFileChooser.APPROVE_OPTION) {
					JonatToolUI.this.outputDirectoryField.setText(fileChooser
							.getSelectedFile().getAbsolutePath());
				}
			}
		});
		panel.add(browseButton);
		browseOutputPanel.add(panel);
		return browseOutputPanel;
	}

	public void actionPerformed(ActionEvent event) {
		if (QUIT_ACTION_COMMAND.equals(event.getActionCommand())) {
			dispose();
		} else {
			String studentCountString = "";
			String skillCountString = "";
			if (configurationProperties.isEmpty()) {
				studentCountString = this.studentCountField.getText();
				skillCountString = this.skillCountField.getText();
			}
			generate(configurationProperties, this.inputFileField.getText(),
					this.outputDirectoryField.getText(), studentCountString,
					skillCountString);
		}
	}

	protected void generate(Properties properties, String inputFileText,
			String outputDirectoryText, String studentCountText,
			String skillCountText) {
		File inputFile;
		File outputDirectory;
		try {
			Validate.notEmpty(inputFileText, "Fichier d'entrée manquant");
			Validate.notEmpty(outputDirectoryText,
					"Répertoire de sortie manquant");
			if (properties.isEmpty()) {
				NumberValidate
						.isNumber(studentCountText,
								"Le champ \"Nombre d'élèves\" contient des données invalides");
				NumberValidate
						.isNumber(skillCountText,
								"Le champ \"Nombre de matières\" contient des données invalides");
				int studentCount = Integer.parseInt(studentCountText);
				int skillCount = Integer.parseInt(skillCountText);
				properties.put("source.skill.count", skillCount);
				properties.put("source.student.count", studentCount);
			}
			inputFile = new File(inputFileText);
			outputDirectory = new File(outputDirectoryText);
			Validate.isTrue(inputFile.exists() && inputFile.isFile(),
					"Le fichier d'entrée n'existe pas ou n'est pas un fichier");
			Validate.isTrue(
					outputDirectory.exists() && outputDirectory.isDirectory(),
					"Le répertoire de sortie n'existe pas ou n'est pas un répertoire");
		} catch (IllegalArgumentException e) {
			logger.error("Erreur lors de la validation du formumaire", e);
			showErrorMessage("Erreur lors de la validation des champs", e);
			return;
		}
		launchGeneration(inputFile, outputDirectory, properties);
	}

	protected void showErrorMessage(String title, Throwable e) {
		JOptionPane.showMessageDialog(JonatToolUI.this, e.getMessage(), title,
				JOptionPane.ERROR_MESSAGE);
	}

	protected void launchGeneration(File inputFile, File outputDirectory,
			Properties properties) {
		try {
			logger.info("Début de l'extraction des notes");
			StudentExtractor studentExtractor = createStudentExtractor(properties);
			OutCome outCome = studentExtractor.extractStudents(inputFile);
			logger.info("Extraction réussie");
			logger.info("Début de la génération des fichiers");
			StudentOutComeGenerator generator = createGenerator(properties);
			generator.generateOutcomes(outCome, outputDirectory);
			logger.info("Génération réussie");
			showMessageDialog("La création des fichiers a réussi !");
		} catch (Exception e) {
			logger.error("Erreur pendant de la génération des fichiers", e);
			showErrorMessage("Erreur pendant la génération des fichiers",
					ExceptionUtils.getRootCause(e));
		}
	}

	protected void showMessageDialog(String message) {
		JOptionPane.showMessageDialog(JonatToolUI.this, message, "Bravo",
				JOptionPane.INFORMATION_MESSAGE);
	}

	protected StudentExtractor createStudentExtractor(Properties properties) {
		return new StudentExtractor(properties);
	}

	protected StudentOutComeGenerator createGenerator(Properties properties) {
		return new StudentOutComeGenerator(properties);
	}

	public static void main(String[] args) throws Exception {
		ClassLoader contextClassLoader = Thread.currentThread()
				.getContextClassLoader();
		DOMConfigurator.configure(contextClassLoader.getResource("log4j.xml"));
		new JonatToolUI();
	}
}
